package com.shanpin.shebao.admin.order;

import java.io.IOException;
import java.util.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.shanpin.shebao.utility.Criterition;
import com.shanpin.shebao.utility.MoreCriteria;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

import com.google.common.collect.ImmutableMap;
import com.shanpin.core.constant.OrderConst;
import com.shanpin.core.constant.RefundType;
import com.shanpin.core.db.NamedSql;
import com.shanpin.core.http.JsonView;
import com.shanpin.core.http.MJsonView;
import com.shanpin.core.status.BaseStatus;
import com.shanpin.core.utils.DateUtil;
import com.shanpin.core.utils.NumberUtil;
import com.shanpin.shebao.admin.ListQueryBuilder;
import com.shanpin.shebao.admin.controller.ResourceController;
import com.shanpin.shebao.admin.excel.ExcelService;
import com.shanpin.shebao.admin.exception.SystemException;
import com.shanpin.shebao.admin.module.channel.ChannelService;
import com.shanpin.shebao.admin.module.city.CityCacheService;
import com.shanpin.shebao.admin.module.user.UserService;
import com.shanpin.shebao.admin.order.model.RefundExportVO;
import com.shanpin.shebao.admin.order.model.RefundListVO;
import com.shanpin.shebao.basedb.model.CityConfig;
import com.shanpin.shebao.common.LoginedService;
import com.shanpin.shebao.common.TResult;
import com.shanpin.shebao.common.URI;
import com.shanpin.shebao.form.OrderRefundForm;
import com.shanpin.shebao.form.PayOrderDetailForm;
import com.shanpin.shebao.form.PayOrderQueryForm;
import com.shanpin.shebao.model.ServiceResult;
import com.shanpin.shebao.utility.PageModel;

/**
 * 订单的退款
 * @author 品讯科技
 *
 */
@Controller
public class OrderRefundController extends ResourceController {

	private final static Logger LOG = LoggerFactory.getLogger(OrderRefundController.class);

	@Autowired
	private UserService userService;
	@Autowired
	private RefundService refundService;
	@Autowired
	private RefundApiService refundApiService;
	@Autowired
	private ChannelService channelService;
	@Autowired
	private ExcelService excelService;
	@Autowired
	private CityCacheService cityCacheService;
	@Autowired
	private RefundQueryService refundQueryService;
	

	/**
	 * 检查全额退款是否合要求 和 必要的提示
	 * @param response
	 * @param form
	 * @throws IOException
	 */
	@RequestMapping(value=URI.ORDER_RESET_REFUND_CHECK, method=RequestMethod.POST)
	public void refundCheck(HttpServletResponse response, OrderRefundForm form) throws IOException {
		if(form.getRefundType() == 0) {
			JsonView.resp(BaseStatus.PARAM_INVALID, "退款类型无效").write(response);
			return;
		}
		TResult<Boolean> ret = refundService.checkRefund(form);
		if (ret.result) {
			JsonView.ok(ImmutableMap.of("batchNo", 
					DateUtil.currentStr("yyyyMMdd_HHmmss")+"_"+ NumberUtil.genRandomNums(4),
					"msg", ret.msg)).write(response);
		} else {
			JsonView.fail(ret.msg).write(response);
		}
	}
	/**
	 * 订单退款
	 * @param request
	 * @param response
	 * @param form
	 * @return
	 * @throws IOException 
	 */
	@RequestMapping(value=URI.ORDER_RESET_REFUND, method=RequestMethod.POST)
	public void refund(HttpServletRequest request, HttpServletResponse response, 
			PayOrderDetailForm form, String batchNo) throws IOException {
		if(form.getRefundType() == 0) {
			throw new SystemException("退款类型 无效！");
		}
		if(form.getRefundApi() < 1 || form.getRefundApi() > 3 ) {
			throw new SystemException("退款方式 无效！");
		}
		
		if(RefundType.PARTIAL_REFUND.getKey() == form.getRefundType()) {
			if(form.getRefundAmount() == null) {
				throw new SystemException("部分退款的金额不能为空！");
			}
			if(StringUtils.isBlank(form.getRefundReason())) {
				throw new SystemException("部分退款的原因不能为空！");
			}
		}
		if (StringUtils.isBlank(batchNo)) {
			JsonView.resp(BaseStatus.PARAM_INVALID, "批次号是空的！").write(response);
			return;
		}

		String opt_user = getLoginUser(request);
		ServiceResult<Boolean> ret = refundService.refund(form, opt_user, batchNo);
		if (null != ret.result && ret.result) {
			JsonView.ok().write(response);
			return;
		}
		JsonView.fail(ret.msg).write(response);
	}
	
	/**
	 * 用户APP上申请退款，后台执行不退款
	 * @param order_no
	 * @param reason
	 * @return
	 */
	@RequestMapping(value=URI.ORDER_EDIT_REJECT_REFUND, method=RequestMethod.POST)
	public Object rejectRefund(String order_no, String reason, HttpServletRequest request) {
		String opt_user = getLoginUser(request);
		if (StringUtils.isBlank(opt_user)) {
			return MJsonView.fail("需要登录才能操作");
		}
		if (StringUtils.isBlank(order_no)) {
			return MJsonView.fail("单号是空的");
		}
		if (StringUtils.isBlank(reason)) {
			return MJsonView.fail("原因是空的");
		}
		boolean ret = refundService.rejectRefund(order_no, reason, opt_user);
		return ret ? MJsonView.ok() : MJsonView.fail();
	}


	@RequestMapping(value=URI.ORDER_LIST_REFUND)
	public ModelAndView refundList(String refund_type, PayOrderQueryForm form, 
			Boolean idcardStar, String batchNo, String reg_channel, HttpServletRequest request) {

		if (null == idcardStar) {
			idcardStar = false;
		}
		if (StringUtils.isBlank(form.getOrder_start_time())) {
			if (StringUtils.isBlank(form.getMonth())) {
				form.setOrder_start_time(DateUtil.dateStr(0, "yyyy-MM-dd"));
			}
			if (!idcardStar) { // 显示身份证号码时才进入代码块。
				// 待处理的退款单 2019-12-24 by jahe.lai
				form.setOrder_status(""+0); 
			}
			
		}
		
		int pageSize = PAGE_SIZE + 90;
		int page = parsePageNo(form.getPageNo());
		form.setIs_kefu(false);
		String opt_user = getLoginUser(request);
		NamedSql ns = ListQueryBuilder.refundListQuery(refund_type, form, batchNo, reg_channel);
		queryWithPayUsers(form.getPayusers(), ns);
		PageModel pageModel = refundQueryService.refundList(idcardStar, page, pageSize, ns);
		ModelAndView mav = new ModelAndView("order/order_refunds");
		mav.addObject("pageModel", pageModel);
		mav.addObject("myBatchNos", refundQueryService.batchNoList(opt_user, form.getOrder_start_time()));
		addCityInfo(pageModel, mav);
		mav.addObject("refund_type", refund_type);
		mav.addObject("payOrderQueryForm", form);	
		mav.addObject("batchNo", batchNo);
		mav.addObject("orderStatus", OrderConst.values());
		mav.addObject("channelCode", LoginedService.getChannel());
		mav.addObject("channels", channelService.listChannel());
		mav.addObject("reg_channel", reg_channel);
		mav.addObject("export_uri", URI.SBA + URI.ORDER_EXPORT_REFUND);
		mav.addObject("doRefund_uri", URI.SBA + URI.ORDER_SUBMIT_REFUND);
		mav.addObject("refund_del_uri", URI.SBA + URI.ORDER_RESET_REFUND_DEL);
		mav.addObject("refund_retry_uri", URI.SBA + URI.ORDER_RESET_REFUND_RETRY);
		mav.addObject("refund_ok_uri", URI.SBA + URI.ORDER_RESET_REFUND_OK);
		mav.addObject("refund_list_statistical",URI.SBA + URI.ORDER_LIST_REFUND_STATISTICAL);
		return mav;
	}
	
	/**
	 * 将帐号批量查询添加到SQL语句。
	 * @param payusers
	 * @param ns
	 */
	private void queryWithPayUsers(String payusers, NamedSql ns) {
		if (StringUtils.isNotBlank(payusers)) {
			List<String> uphoneList = Arrays.asList(payusers.split(","));
			Set<Integer> uidSet = new HashSet<>(uphoneList.size());
			for (String phone : uphoneList) {
				int id = userService.queryUid(phone.trim());
				if (id > 0) {
					uidSet.add(id);
				}
			}
			if (uidSet.size() > 0) {
				ns.add(uidSet, " AND bo.pay_uid IN (:payusers)", "payusers");
			}
		}
	}
	
	// 本分页的城市
	private void addCityInfo(PageModel pm, ModelAndView mav) {
		List<RefundListVO> recordList = pm.getRecordList();
		Set<Integer> cityCodes = new HashSet<>();
		for (RefundListVO vo : recordList) {
			cityCodes.add(vo.getCity_code());
		}
		List<Integer> existedCities = new ArrayList<>(cityCodes);
		List<CityConfig> existedCityList = new ArrayList<>(existedCities.size());
		TreeSet<CityConfig> pCitySet = cityCacheService.cityCode2Exist(existedCities, existedCityList);
		mav.addObject("existedCityList", existedCityList);
		mav.addObject("pCitySet", pCitySet);
	}
	
	@RequestMapping(value=URI.ORDER_CHANNEL_LIST_REFUND)
	public ModelAndView channelRefundList(String refund_type, 
			PayOrderQueryForm form, HttpServletRequest request) {
		form.setPay_channel(String.valueOf(LoginedService.getChannel()));
		ModelAndView mav =  refundList(refund_type, form, true, "", "", request);
		return mav;
	}
	
	/**
	 * 触发退款单的处理，发送到第三方支付平台退款。
	 * @return
	 * @throws IOException 
	 */
	@RequestMapping(value=URI.ORDER_SUBMIT_REFUND)
	public void submitRefund(HttpServletResponse resp) throws IOException {
//		int hm = Integer.parseInt(DateTime.now().toString("HHmm"));
//		if (1448 < hm && 1458 > hm) {
//			JsonView.fail("下午2点50分至56分是数据备份时间，稍后再操作").write(resp);
//			return;
//		}
		String opt_user = LoginedService.getUsername();
		String msg = refundApiService.submitRefund(opt_user);
		if (StringUtils.isNotBlank(msg)) {
			JsonView.fail("调用接口退款失败,原因：" + msg).write(resp);
			return;
		}
		JsonView.ok("处理完成").write(resp);
	}
		
	
	@RequestMapping(value=URI.ORDER_EXPORT_REFUND, method=RequestMethod.POST)
	public void exportRefundList(String refund_type, PayOrderQueryForm form, String batchNo, HttpServletResponse resp) throws IOException {
		if (LoginedService.getChannel() > 0) { // 渠道用户不能导出
			JsonView.fail("未能通过检验").write(resp);
			return;
		}
		if (StringUtils.isBlank(form.getOrder_start_time())) {
			if (StringUtils.isBlank(form.getMonth())) {
				form.setOrder_start_time(DateUtil.dateStr(-45, "yyyy-MM-dd"));
			}
		}
		NamedSql ns = ListQueryBuilder.refundListQuery(refund_type, form, batchNo, "");
		queryWithPayUsers(form.getPayusers(), ns);
		List<RefundExportVO> recordList = refundQueryService.exportRefundList(ns);
		String[] headers = { "姓名", "购买类型", "购买月份", 
				"退款类型", "退款方式", "退款金额", "退款状态", "订单服务费", "原始订单状态",
				"是否补缴","否打包购","是否退费结算","时间",
				"退款人", "退款原因", "订单号", "支付流水号", 
				"渠道"};
		String[] fields = { "user_name", "pay_for", "for_month", 
				"opt_type", "opt_api", "amount", "opt_status", "order_charge", "status",
				"added","isPageBuy","isRefundSettlement","gen_time",
				"opt_user", "remark", "order_no", "pay_no",
				"pay_channel"};
		if (recordList != null && recordList.size() > 0) {
			String fileName = "refund_"+form.getOrder_start_time()+".xls";
			excelService.exportExcel(fileName, "订单退款表", headers,fields,recordList,resp);
		}
	}
	
	@RequestMapping(value=URI.ORDER_RESET_REFUND_DEL, method=RequestMethod.POST)
	public ModelAndView delById(HttpServletResponse response, Integer id) throws IOException {
		if (null == id || id < 1) {
			return MJsonView.resp(BaseStatus.PARAM_INVALID, "ID值无效");
		}
		boolean ret = refundService.delById(id);
		return ret ? MJsonView.ok() : MJsonView.fail("未能删除成功，确认是可删除的状态");
	}
	

	@RequestMapping(value=URI.ORDER_RESET_REFUND_RETRY, method=RequestMethod.POST)
	public ModelAndView retryRefund(Integer id) throws IOException {
		if (null == id || id < 1) {
			return MJsonView.resp(BaseStatus.PARAM_INVALID, "ID值无效");
		}
		boolean ret = refundService.retry(id);
		return ret ? MJsonView.ok() : MJsonView.fail("未能设置成功");
	}
	

	/**
	 * 将退款不成功的退款单设置成退款成功。
	 * @param id
	 * @return
	 * @throws IOException
	 */
	@RequestMapping(value=URI.ORDER_RESET_REFUND_OK, method=RequestMethod.POST)
	public ModelAndView refundOK(Integer id) throws IOException {
		if (null == id || id < 1) {
			return MJsonView.resp(BaseStatus.PARAM_INVALID, "ID值无效");
		}
		LOG.error("手动调用退款成功：{}, {}", id, LoginedService.getUsername());
		ServiceResult<Boolean> ret = refundApiService.apiRefundNotify(id, OrderConst.PRE_PAY);
		return (null != ret.result && ret.result) ? MJsonView.ok() : MJsonView.fail(
				StringUtils.isNotBlank(ret.msg)? ret.msg : "设置成退款成功时出现了错误");
	}


	@RequestMapping(value= URI.ORDER_LIST_REFUND_STATISTICAL)
	public ModelAndView orderChannelStatistical(String refund_type, PayOrderQueryForm form,
												Boolean idcardStar, String batchNo,
												String reg_channel, HttpServletRequest request) {
		int channel = LoginedService.getChannel();
		if(channel > 0){
            form.setPay_channel(String.valueOf(channel));
        }
		if (null == idcardStar) {
			idcardStar = false;
		}
		if (StringUtils.isBlank(form.getOrder_start_time())) {
			if (StringUtils.isBlank(form.getMonth())) {
				form.setOrder_start_time(DateUtil.dateStr(0, "yyyy-MM-dd"));
			}
			if (!idcardStar) { // 显示身份证号码时才进入代码块。
				// 待处理的退款单 2019-12-24 by jahe.lai
				form.setOrder_status(""+0);
			}
		}
		form.setIs_kefu(false);
		NamedSql ns = ListQueryBuilder.refundListQuery(refund_type, form, batchNo, reg_channel);
		queryWithPayUsers(form.getPayusers(), ns);
		Map<String, Integer> map = refundQueryService.orderStatistical(idcardStar,ns);
		return MJsonView.ok(map);
	}
}
